Overview

Vision can be used to aim the robot.
It is most suitable to use when targets are easily distinguishable (bright yellow cubes, orange balls), or for games that have lots of vision targets.

Implementing vision has two steps:

  • Vision detection (easy) - Camera can detect the target reliably without confusing it with surrounding objects.
  • Vision integration (hard) - Combining vision with the robot

Team 5901 utilzes the Limelight Camera.

Link Description
Mounting/Wiring/Imagine/Networking setup http://docs.limelightvision.io/en/latest/getting_started.html#
Theory of how a vision processing works. Highly recommended to read to understand process. http://docs.limelightvision.io/en/latest/theory.html
How to tune the limelight http://docs.limelightvision.io/en/latest/vision_pipeline_tuning.html

Vision Code

The vision subsystem code has been created in previous years and can be reused.
Several methods were created that can be called by different commands, can be summarized in the following table:

Method Name Description Example
getTx() returns horizontal offset angle to camera m_VisionSubsystem.getTx();
getTy() returns vertical offset angle to camera m_VisionSubsystem.getTy();
getTa() returns target area, used to approximate distance to target) m_VisionSubsystem.getTa();
targetAvailable() returns a boolean if a target is detected m_VisionSubsystem.targetAvailable();
turnOffLED() turns off camera lights m_VisionSubsystem.turnOffLED();
turnOnLED() turns on camera lights m_VisionSubsystem.turnOnLED();

VisionSubsystem.java

/*----------------------------------------------------------------------------*/
/* Copyright (c) 2019 FIRST. All Rights Reserved.                             */
/* Open Source Software - may be modified and shared by FRC teams. The code   */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project.                                                               */
/*----------------------------------------------------------------------------*/

package frc.robot.subsystems;

import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.wpilibj2.command.SubsystemBase;

public class VisionSubsystem extends SubsystemBase {

  public VisionSubsystem() {   

  }

  //Get Horizontal Offset Angle
  public double getTx(){
    return NetworkTableInstance.getDefault().getTable("limelight").getEntry("tx").getDouble(0);
  }

  //Get Vertical Offset Angle
  public double getTy(){
    return NetworkTableInstance.getDefault().getTable("limelight").getEntry("ty").getDouble(0);
  }

  //Get Target Area
  public double getTa(){
    return NetworkTableInstance.getDefault().getTable("limelight").getEntry("ta").getDouble(0);
  }

  //Return true if target is available, otherwise false
  public boolean targetAvailable(){
    if (NetworkTableInstance.getDefault().getTable("limelight").getEntry("tv").getDouble(0) < 1.0)
    {
      return false;
    }
    else
    {
      return true;
    }  
  }

  public void turnOffLED(){
    NetworkTableInstance.getDefault().getTable("limelight").getEntry("ledMode").setNumber(1);
  }

  public void turnOnLED(){
    NetworkTableInstance.getDefault().getTable("limelight").getEntry("ledMode").setNumber(3);    
  }

  @Override
  public void periodic() {
    // This method will be called once per scheduler run
  }
}